﻿using System;
using System.Drawing;
using System.Windows.Forms;

namespace NhanDang
{
    class ImageProcessing
    {
       /* public static Bitmap ToBinary(Bitmap bm, Byte band)
        {
            Bitmap bitmap = new Bitmap(bm);
            int x, y;
            Color c;
            for (y = 0; y < bm.Height - 1; y++)
            {
                for (x = 0; x < bm.Width - 1; x++)
                {
                    c = bm.GetPixel(x, y);
                    if (c.R < band)
                        bitmap.SetPixel(x, y, Color.FromArgb(0, 0, 0));
                    else
                        bitmap.SetPixel(x, y, Color.FromArgb(255, 255, 255));
                }
            }
            return bitmap;
        }*/

        //dùng kỹ thuật LockBits de xu ly anh
        public static Bitmap ToBinaryLocBits(Bitmap bm, Byte band)
        {
            Bitmap bitmap = new Bitmap(bm);
            Rectangle rec = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(rec, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            Int32 bytes = Math.Abs(bmpData.Stride) * bitmap.Height;// Abs: tri tuyet doi
            Byte[] rgbValues = new Byte[bytes];
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);//sao chép các ô nhớ từ ptr vào mảng byte

            //Tại sao lại có step là 4 (counter+=4) ? Đối với lớp Bitmap,
            //khi ta khai báo khởi tạo bằng phương thức new sẽ nhận được đầu vào là một bitmap định dạng 32bit.Code: Bitmap bitmap = new Bitmap(bm);
            for (int counter = 0; counter < rgbValues.Length - 1; counter += 4)
            {
                Byte colorR = rgbValues[counter];
                Byte colorG = rgbValues[counter + 1];
                Byte colorB = rgbValues[counter + 2];
                if (colorR < band || colorB <band || colorG <band)
                {
                    rgbValues[counter + 0] = 0;// 0:mau den
                    rgbValues[counter + 1] = 0;
                    rgbValues[counter + 2] = 0;
                }
                else
                {
                    rgbValues[counter + 0] = 255;// 255:mau trang
                    rgbValues[counter + 1] = 255;
                    rgbValues[counter + 2] = 255;
                }
            }  
            System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
            bitmap.UnlockBits(bmpData);
            return bitmap;
        }

        /* - Giải thuật trên chủ yêu dựa trên 2 phương thức:
Code:
   
 System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);  
 System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
         - Nhiệm vụ của chúng là sao chép các ô nhớ từ ptr vào mảng byte và ngược lại.*/

        public static Bitmap ResizeImage(Bitmap bm)
        {
            Point pBegin = new Point(bm.Width,bm.Height);
            Point pEnd = new Point(0,0);
            Bitmap bitmap = new Bitmap(bm);
            Rectangle rec = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(rec, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            Int32 bytes = Math.Abs(bmpData.Stride) * bitmap.Height;
            Byte[] rgbValues = new Byte[bytes];
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
            Byte color;
            for (int counter = 0; counter < rgbValues.Length - 1; counter += 4)
            {
                color = rgbValues[counter];
                if (color == 0)
                {
                    Point p = new Point((counter - (counter / bmpData.Stride) * bmpData.Stride)/4, counter / bmpData.Stride);
                    if (p.X < pBegin.X)
                    {
                        pBegin.X = p.X;
                    }
                    if (p.Y < pBegin.Y)
                    {
                        pBegin.Y = p.Y;
                    }
                    if (p.X > pEnd.X)
                    {
                        pEnd.X = p.X;
                    }
                    if (p.Y > pEnd.Y)
                    {
                        pEnd.Y = p.Y;
                    }
                }
            }
            bitmap.UnlockBits(bmpData);
            if (pEnd.X <= pBegin.X)
            {
                return bitmap;
            }
            else
            {
                return bitmap.Clone(new Rectangle(pBegin, new Size(pEnd.X - pBegin.X + 1, pEnd.Y - pBegin.Y + 1)), bitmap.PixelFormat);
            }
        }

        public static double[] arrInput(Bitmap bm, int width, int height, int z)
        {
            double[] result = new double[width*height];
            int[,] arr = new int[bm.Height, bm.Width];
            Bitmap bitmap = new Bitmap(bm);
            Rectangle rec = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(rec, System.Drawing.Imaging.ImageLockMode.ReadWrite, bitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            Int32 bytes = Math.Abs(bmpData.Stride) * bitmap.Height;
            Byte[] rgbValues = new Byte[bytes];
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
            for (int counter = 0; counter < rgbValues.Length - 1; counter += 4)
            {
                Point p = new Point((counter - (counter / bmpData.Stride) * bmpData.Stride) / 4, counter / bmpData.Stride);
                if (rgbValues[counter]==0)
                {
                    arr[p.Y, p.X] = 1;
                }
                else
                {
                    arr[p.Y, p.X] = 0;
                }
            }

            int[,] black = new int[height, width];
            int[,] white = new int[height, width];
            for (int i = 0; i < bm.Height; i++)
            {
                for (int j = 0; j < bm.Width; j++)
                {
                    int indexR = i * height / bm.Height;
                    int indexC = j * width / bm.Width;
                    if (arr[i,j] == 1)
                    {
                        black[indexR, indexC]++;
                    }
                    else
                    {
                        white[indexR, indexC]++;
                    }
                }
            }
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    result[i * width + j] = black[i, j] >= (white[i, j] / z) ? 1 : 0;
                }
            }
            return result;
        }

        public static Bitmap ArrayToBitMap(double[] arr, int height, int width)
        {
            Bitmap bt = new Bitmap(width, height);
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    bt.SetPixel(j, i, arr[width * i + j] == 0 ? Color.White : Color.Black);
                }
            }
            return bt;
        }
    }
}
